clear
close ALL;
clc;
% 打开二进制文件
%fileID = fopen('12151112.DAT', 'rb');
%fileID = fopen('01181304.DAT', 'rb');
%fileID = fopen('12141808.DAT', 'rb');
%fileID = fopen('03151500.DAT', 'rb');
%fileID = fopen('12201341.DAT', 'rb');
%fileID = fopen('03180827.DAT', 'rb');           %正弦波 10Hz
fileID = fopen('5Hz.DAT', 'rb');           %正弦波 2Hz,50mV的5%分压
%% 总文件头Head  ----------------------------------------------
% 32bit固定值
% 读取标识符（8个字节）
identifier = fread(fileID, 8, 'uint8');
% 读取版本信息（6个字节）
version = fread(fileID, 6, 'uint8');
% 读取格式标识符（2个字节）
formatIdentifier = fread(fileID, 2, 'uint8');
% 读取二进制形式（1个字节）
binaryForm = fread(fileID, 1, 'uint8');          % 注意，AP108设备的存储格式是L端模式，数值先低位后高位，例如看r_size
% 读取汉字形式（1个字节）
chineseForm = fread(fileID, 1, 'uint8');
% 读取记录次数（4个字节）
%recordCount = fread(fileID, 1, 'uint32');      % 为ASCII格式，因此不能直接按uint32读取
recordCount = fread(fileID, 4, 'uint8');
% 读取预留信息（10个字节）
reservedInfo = fread(fileID, 10, 'uint8');
% 打印以上信息
disp('*文件头 Head（32字节固定）: ');
charIdentifier = char(identifier)';
disp(['  识别子（8 字节）: ',charIdentifier]);
charVersion = char(version)';
disp(['  Version（6字节）:',charVersion]);
charFormatIdentifier =char(formatIdentifier)';
disp(['  Format识别子（2字节）: ',charFormatIdentifier]);
charBinaryForm  =char(binaryForm)';
disp(['  形式（1字节）: ',charBinaryForm]);      
charChineseForm  =char(chineseForm)';
disp(['  汉字（1字节）: ',charChineseForm]);
charRecordCount  =char(recordCount)';
disp(['  记录回数（4字节）字符: ',charRecordCount]);
charReservedInfo  =char(reservedInfo)';
disp(['  Reserve（10字节）: ',charReservedInfo]);

%% 记录单位Record Information (Code=10)----------------------------------------------
%读取尺寸（4字节）
r_size = fread(fileID,1,'uint32');
%读取识别码（4字节）
r_identifier = fread(fileID,1,'uint32');
%读取序号（4字节）
r_xuhao = fread(fileID,1,'uint32');
%读取Reserve（4字节）
r_Reserve = fread(fileID,1,'uint32');
% 打印以上信息
disp('*记录单位 Record Info(Code=10): ');
%char_r_size = char(r_size)';
disp(['  大小（4字节）: ',num2str(r_size)]);
disp(['  识别码（4字节）: ',num2str(r_identifier)]);
disp(['  序号（4字节）: ',num2str(r_xuhao)]);
disp(['  Reserve（4字节）: ',num2str(r_Reserve)]);

%% 基本信息Basic Information (Code=100)----------------------------------------------
bi_size = fread(fileID,1,'uint32');
bi_code = fread(fileID,1,'uint32');
bi_fuzhu = fread(fileID,1,'uint32');
bi_rsv1 = fread(fileID,1,'uint32');
bi_dataform = fread(fileID,1,'uint32');
bi_noch = fread(fileID,1,'uint32');
bi_totalframe = fread(fileID,1,'uint32');
bi_rsv2 = fread(fileID,1,'uint32');
bi_year = fread(fileID,1,'uint32');
bi_month = fread(fileID,1,'uint32');
bi_day = fread(fileID,1,'uint32');
bi_hour = fread(fileID,1,'uint32');
bi_min = fread(fileID,1,'uint32');
bi_second = fread(fileID,1,'uint32');
bi_time = fread(fileID,20,'uint8');
bi_power_hz = fread(fileID,1,'uint32');
bi_rsv3 = fread(fileID,16,'uint8');
bi_comment = fread(fileID,32,'uint8');
% 打印以上信息
disp('*基本信息 Basic Information(Code=100): ');
disp(['  size（4字节）: ',num2str(bi_size)]);
disp(['  code（4字节）: ',num2str(bi_code)]);
disp(['  子信息序列号（4字节）: ',num2str(bi_fuzhu)]);
disp(['  Reserve（4字节）: ',num2str(bi_rsv1)]);
disp(['  日期格式（4字节）: ',num2str(bi_dataform)]);
disp(['  通道数量（4字节）: ',num2str(bi_noch)]);
disp(['  totalframe（4字节）: ',num2str(bi_totalframe)]);
disp(['  Reserve（4字节）: ',num2str(bi_rsv2)]);
disp('   记录开始时间: ');
disp(['    年（4字节）: ',num2str(bi_year)]);
disp(['    月（4字节）: ',num2str(bi_month)]);
disp(['    日（4字节）: ',num2str(bi_day)]);
disp(['    时（4字节）: ',num2str(bi_hour)]);
disp(['    分（4字节）: ',num2str(bi_min)]);
disp(['    秒（4字节）: ',num2str(bi_second)]);
charDateTime  =char(bi_time)';
disp(['    日/月/年 时.分.秒（20字节ASCII）: ',charDateTime]);
disp(['    电源周波（4字节）: ',num2str(bi_power_hz)]);
charReserve3  =char(bi_rsv3)';
disp(['  Reserve（16字节）: ',charReserve3]);
charComment  =char(bi_comment)';
disp(['  Comment（32字节）: ',charComment]);


%% 患者信息 Patient Information (Code=130)----------------------------------------------
patient_head_size = fread(fileID,1,'uint32');                              % 0-3   byte,   4 bytes,  BIN
patient_head_code = fread(fileID,1,'uint32');                              % 4-7   byte,   4 bytes,  BIN, Code = 130
patient_subsequence_no = fread(fileID,1,'uint32');                         % 8-11  byte,   4 bytes,  BIN, 固定为00h
patient_reserve_1 = fread(fileID,1,'uint32');                              % 12-15 byte,   4 bytes
patient_item_no = fread(fileID,1,'uint32');                                % 16-19 byte,   4 bytes,  BIN
patient_reserve_2 = fread(fileID,1,'uint32');                              % 20-23 byte,   4 bytes,  BIN
% 打印以上信息
disp('*患者信息 Patient Information(Code=130): ');
disp(['  size（4字节）: ',num2str(patient_head_size)]);
disp(['  code（4字节）: ',num2str(patient_head_code)]);
disp(['  subsequence number（4字节）: ',num2str(patient_subsequence_no),'（固定值00h）']);
disp(['  reserve（4字节）: ',num2str(patient_reserve_1)]);
disp(['  item number（4字节）: ',num2str(patient_item_no)]);
disp(['  reserve（4字节）: ',num2str(patient_reserve_2)]);
% 每个病人有ID号、性别、年龄、睡眠状态等子条目信息，如下
for(iii=1:patient_item_no)
%     patient_item_size = 0; patient_item_key = 0; patient_item_value = '';
    patient_item_size = fread(fileID,1,'uint32');                              % 24-27 byte,   4 bytes,  BIN
    patient_item_key = fread(fileID,1,'uint32');                               % 28-31 byte,   4 bytes,  BIN
    patient_value_length = patient_item_size - 8;                             % 计算下面patient_item_value的长度，要减去2个4 bytes
    patient_item_value = fread(fileID,patient_value_length,'uint8');
    % 打印各子信息
    %{
    disp(['  item No. ', num2str(iii) ,': ']);
    disp(['    item_size（4字节）: ',num2str(patient_item_size)]);
    disp(['    item_key（4字节）: ',num2str(patient_item_key)]);
    char_patient_item_value  =char(patient_item_value)';
    disp(['    item_value（', num2str(patient_value_length) ,'字节）: ',char_patient_item_value]);
    %}
end


%% 事件信息 Event Information (Code=200)----------------------------------------------
event_head_size = fread(fileID,1,'uint32');                                % 0-3   byte,   4 bytes,  BIN
event_head_code = fread(fileID,1,'uint32');                                % 4-7   byte,   4 bytes,  BIN, Code = 130
event_subsequence_no = fread(fileID,1,'uint32');                           % 8-11  byte,   4 bytes,  BIN, 固定为00h
event_reserve_1 = fread(fileID,1,'uint32');                              % 12-15 byte,   4 bytes
event_item_no = fread(fileID,1,'uint32');                                  % 16-19 byte,   4 bytes,  BIN
event_reserve_2 = fread(fileID,1,'uint32');                                % 20-23 byte,   4 bytes,  BIN
% % 打印以上信息
disp('*事件信息 Event Information(Code=200): ');
disp(['  size（4字节）: ',num2str(event_head_size)]);
disp(['  code（4字节）: ',num2str(event_head_code)]);
disp(['  subsequence number（4字节）: ',num2str(event_subsequence_no),'（固定值00h）']);
disp(['  reserve（4字节）: ',num2str(event_reserve_1)]);
disp(['  item number（4字节）: ',num2str(event_item_no)]);
disp(['  reserve（4字节）: ',num2str(event_reserve_2)]);
% 每个事件记录开始，记录结束，事件1、2、3...等子条目信息，如下
for(iii=1:event_item_no)
    event_item_size = fread(fileID,1,'uint32');                              % 24-27 byte,   4 bytes,  BIN
    event_item_key = fread(fileID,1,'uint32');                               % 28-31 byte,   4 bytes,  BIN
    event_value_length = event_item_size - 8;                               % 计算下面event_item_value的长度，要减去2个4 bytes
    event_item_value = fread(fileID,event_value_length,'uint8');
    % 打印各子事件
    %{
    disp(['  item No. ', num2str(iii) ,': ']);
    disp(['    item_size（4字节）: ',num2str(event_item_size)]);
    disp(['    item_key（4字节）: ',num2str(event_item_key)]);
    char_event_item_value  =char(event_item_value)';
    disp(['    item_value（', num2str(event_value_length) ,'字节）: ',char_event_item_value]);
    %}
end

%% 频道信息 Channel Information (Code=120)----------------------------------------------
channel_head_size = fread(fileID,1,'uint32');                                % 0-3   byte,   4 bytes,  BIN
channel_head_code = fread(fileID,1,'uint32');                                % 4-7   byte,   4 bytes,  BIN, Code = 130
channel_subsequence_no = fread(fileID,1,'uint32');                           % 8-11  byte,   4 bytes,  BIN, 固定为00h
channel_reserve_1 = fread(fileID,1,'uint32');                                % 12-15 byte,   4 bytes
channel_no = fread(fileID,1,'uint32');                                       % 16-19 byte,   4 bytes,  BIN
channel_channel_NCS = fread(fileID,1,'uint32');                              % 20-23 byte,   4 bytes,  BIN  
channel_reserve_2 = fread(fileID,8,'uint8');                                 % 24-31 byte,   8 bytes
% % 打印以上信息
disp('*频道信息 Channel Information(Code=120): ');
disp(['  size（4字节）: ',num2str(channel_head_size)]);
disp(['  code（4字节）: ',num2str(channel_head_code)]);
disp(['  subsequence number（4字节）: ',num2str(channel_subsequence_no),'（固定值00h）']);
disp(['  reserve（4字节）: ',num2str(channel_reserve_1)]);
disp(['  channel number（4字节）: ',num2str(channel_no)]);
disp(['  信道子信息的大小(NCS)（4字节）: ',num2str(channel_channel_NCS)]);
char_channel_reserve_2  =char(channel_reserve_2)';
disp(['  reserve（8字节）: ',char_channel_reserve_2]);
% 每个通道的信息，如果有channel_no个通道，则每个通道有channel_channel_NCS长度的信息（一般为256），如下
for(iii=1:channel_no)
   channel_a_size = fread(fileID,1,'uint32');
   channel_a_code = fread(fileID,1,'uint32');   
   channel_a_no   = fread(fileID,1,'uint32');   
   channel_a_reserve_1 = fread(fileID,1,'uint32'); 
   channel_a_num   = fread(fileID,1,'uint32');   
   channel_a_definition = fread(fileID,1,'uint32');   % 通道定义1EEG，2EEG，3EEG，4EEG，5EOG，6EOG,7EMG,8ECG
   channel_a_signal = fread(fileID,1,'uint32');
   channel_a_record_form = fread(fileID,1,'uint32');
   channel_a_samp_freq = fread(fileID,1,'uint32');
   channel_a_cal = fread(fileID,1,'uint32');
   channel_a_cal_ad= fread(fileID,1,'uint32');
   channel_a_off_ad = fread(fileID,1,'uint32');
   channel_a_off_cal = fread(fileID,1,'uint32');
   channel_a_cal_freq = fread(fileID,1,'uint32');
   channel_a_filter_l_t = fread(fileID,1,'uint32');
   channel_a_filter_h = fread(fileID,1,'uint32');
   channel_a_amp = fread(fileID,1,'uint32');
   channel_a_rev = fread(fileID,1,'uint32');
   channel_a_label = fread(fileID,16,'uint8');
   channel_a_unit = fread(fileID,16,'uint8');
   channel_a_reserv2 = fread(fileID,92,'uint8');
   channel_a_comment = fread(fileID,60,'uint8');
   % 打印各通道的子信息
   %{
   disp(['    channel ',num2str(iii),' Info（', num2str(channel_channel_NCS),'字节）: ']);
   disp(['      size: ', num2str(channel_a_size)]);
   disp(['      code: ', num2str(channel_a_code)]);
   disp(['      no: ', num2str(channel_a_no)]);
   disp(['      reserve: ', num2str(channel_a_reserve_1)]);
   disp(['      num: ', num2str(channel_a_num)]);
   disp(['      definition: ', num2str(channel_a_definition)]);
   disp(['      record form: ', num2str(channel_a_record_form)]);
   disp(['      sampling frequency: ', num2str(channel_a_samp_freq)]);
   disp(['      Cal: ', num2str(channel_a_cal)]);
   disp(['      Cal AD: ', num2str(channel_a_cal_ad)]);
   disp(['      Off. AD: ', num2str(channel_a_off_ad)]);
   disp(['      Off. Cal: ', num2str(channel_a_off_cal)]);
   disp(['      Cal. Freq.: ', num2str(channel_a_cal_freq)]);
   disp(['      Filter (L)(T): ', num2str(channel_a_filter_l_t)]);
   disp(['      Filter (H): ', num2str(channel_a_filter_h)]);
   disp(['      Amp.: ', num2str(channel_a_amp)]);
   disp(['      Rev: ', num2str(channel_a_rev)]);
   char_channel_a_label  =char(channel_a_label)';
   disp(['      Label: ',char_channel_a_label]);
   char_channel_a_unit  =char(channel_a_unit)';
   disp(['      unit: ',char_channel_a_unit]);
   char_channel_a_reserv2  =char(channel_a_reserv2)';
   disp(['      reserve: ',char_channel_a_reserv2]);
   char_channel_a_comment  =char(channel_a_comment)';
   disp(['      comment: ',char_channel_a_comment]);
   %}
end

%% 未知数据 Unknown data(Code=2700)----------------------------------------------
unknown_size = fread(fileID,1,'uint32');                                % 0-3   byte,   4 bytes,  BIN
unknown_code = fread(fileID,1,'uint32');                                % 4-7   byte,   4 bytes,  BIN, Code = 130
unknown_content = fread(fileID,unknown_size-8,'uint8');
% % 打印以上信息
disp('*位置数据 Unknown Data (Code=2700): ');
disp(['  size（4字节）: ',num2str(unknown_size)]);
disp(['  code（4字节）: ',num2str(unknown_code)]);

%% 帧集数据 Frame data(Code=140)----------------------------------------------
data_size = fread(fileID,1,'uint32');                                % 0-3   byte,   4 bytes,  BIN
data_code = fread(fileID,1,'uint32');                                % 4-7   byte,   4 bytes,  BIN, Code = 130
data_subsequence_no = fread(fileID,1,'uint32');                      % 8-11  byte,   4 bytes,  BIN, 固定为00h
data_reserve_1 = fread(fileID,1,'uint32');                           % 12-15 byte,   4 bytes
frame_duration = fread(fileID,1,'uint32');                            % 16-19 byte,   4 bytes
frame_frame_length = fread(fileID,1,'uint32');                            % 20-23 byte,   4 bytes
frame_frame_num = fread(fileID,1,'uint32');                            % 24-27 byte,   4 bytes
data_reserve_2 = fread(fileID,1,'uint32');                           % 28-31 byte,   4 bytes
data_content = fread(fileID,data_size-32,'uint8');
raw_data = build_data(data_content,channel_no,channel_a_samp_freq,frame_duration,frame_frame_length,frame_frame_num);


% % 打印以上信息
disp('*帧集数据 Frame data(Code=140): ');
disp(['  size（4字节）: ',num2str(data_size)]);
disp(['  code（4字节）: ',num2str(data_code)]);
disp(['  subsequence number（4字节）: ',num2str(data_subsequence_no),'（固定值00h）']);
disp(['  reserve（4字节）: ',num2str(data_reserve_1)]);
disp(['  frame sduration (second)（4字节）: ',num2str(frame_duration)]);
disp(['  frame length （4字节）: ',num2str(frame_frame_length)]);
disp(['  frame number （4字节）: ',num2str(frame_frame_num)]);
disp(['  reserve（4字节）: ',num2str(data_reserve_2)]);

%% 终止符 End boundary(Code=000)----------------------------------------------
end_boundary_1 = fread(fileID,1,'uint32'); 
end_boundary_2 = fread(fileID,1,'uint32'); 
end_boundary_3 = fread(fileID,1,'uint32'); 
end_boundary_4 = fread(fileID,1,'uint32'); 
disp('*帧集数据 Frame data(Code=000): ');
disp(['  size（4字节）: ',num2str(end_boundary_1)]);
disp(['  size（4字节）: ',num2str(end_boundary_2)]);
disp(['  size（4字节）: ',num2str(end_boundary_3)]);
disp(['  size（4字节）: ',num2str(end_boundary_4)]);


%% 画出原始数据——测试用
draw_data(raw_data,channel_no,channel_a_samp_freq,frame_duration,frame_frame_length,frame_frame_num);

% 关闭文件
fclose(fileID);


%% 函数：读信号数据，并把数据存为MxN数组，M为通道数，N为数据长度，例如12X192000
function [data_matrix] = build_data(raw_data,channels,samplerate,duraion,length,num)
    sample_length = samplerate * num;                        % 计算每通道的数据长度，一点2Bytes
    data_matrix = zeros(channels,sample_length); 
    for (jjj=1:num)
        sample_a_frame = (raw_data((jjj-1)*length+24+1:(jjj)*length))';
        % size(sample_a_frame) % = 12 x (通道*采样率*2byte)
        for(kkk = 1:channels)
            channel_bias = (kkk-1)*samplerate*2;
            for(iii = 1: samplerate)
                data_matrix(kkk,(jjj-1)*samplerate+iii) = typecast(uint8([sample_a_frame(channel_bias+iii*2-1),sample_a_frame(channel_bias+iii*2)]),'int16');
            end
        end
    end

end
%% 显示画出来的函数，注意波形经过了归一化，单位尺度变了
function draw_data(data_matrix,channels,samplerate,duraion,length,num)
    %size(data_matrix) %12 x (采样率*秒长)
    ttt = 1:samplerate*num;
    figure;
    for(nnn=1:channels)
        plot(ttt,(data_matrix(nnn,ttt)/max(data_matrix(nnn,:)))+(12-nnn)*2);
        hold on;
    end
end

% % 存储解析出的信息到字典
% headerInfo = struct(...
%     'Identifier', char(identifier), ...
%     'Version', char(version), ...
%     'FormatIdentifier', char(formatIdentifier), ...
%     'BinaryForm', char(binaryForm), ...
%     'ChineseForm', char(chineseForm), ...
%     'RecordCount', recordCount, ...
%     'ReservedInfo', char(reservedInfo) ...
% );
% recordInfo = struct( ...
%     'r_size',r_size, ...
%     'r_identifier',r_identifier, ...
%     'r_xuhao',r_xuhao, ...
%     'r_Reserve',r_Reserve ...
%     );
% Basic_information = struct( ...
%     'Size',bi_size,...
%     'Code',bi_code, ...
%     'Fuzhu',bi_fuzhu, ...
%     'Rsv1',bi_rsv1, ...
%     'dataform',bi_dataform, ...
%     'Noch',bi_noch ,...
%     'Totalframe',char(bi_totalframe) ,...
%     'Rsv2', bi_rsv2,...
%     'Year', bi_year,...
%     'Month', bi_month,...
%     'Day', bi_day,...
%     'Hour', bi_hour,...
%     'Min', bi_min,...
%     'Second',bi_second ,...
%     'Time', char(bi_time),...
%     'Rsv3',char(bi_rsv3),...
%     'Comment',char(bi_comment)...
%     );
% % 将患者信息存储到字典结构体
% Patient_information = struct( ...
%     'exam_number', exam_number, ...
%     'patient_id', patient_id, ...
%     'patient_name', patient_name, ...
%     'gender', gender, ...
%     'age', age, ...
%     'comment1',comment1, ...
%     'comment2',comment2 ...
% );


% 保存字典为MAT文件
%save('header.mat', 'headerInfo',"recordInfo",'Basic_information',"Patient_information");
